package cn.itsource.pethome.user.service.impl;

import cn.itsource.pethome.basic.service.impl.BaseServiceImpl;
import cn.itsource.pethome.user.contant.WeChatContant;
import cn.itsource.pethome.user.domain.User;
import cn.itsource.pethome.user.domain.WxUser;
import cn.itsource.pethome.user.mapper.UserMapper;
import cn.itsource.pethome.user.mapper.WxUserMapper;
import cn.itsource.pethome.user.service.IWxChatService;
import cn.itsource.pethome.utils.*;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class WxChatServiceImpl extends BaseServiceImpl<WxUser> implements IWxChatService {

    @Autowired
    private WxUserMapper wxUserMapper;

    @Autowired
    private UserMapper userMapper;

    @Override
    public AjaxResult loginOrBinder(Map<String, String> map) {
        //根据code获取token
        String token_url = WeChatContant.TOKEN_URL.replace("APPID", WeChatContant.APPID)
                .replace("SECRET", WeChatContant.SECRET)
                .replace("CODE", map.get("code"));
        //以get请求响应，响应内容是：
        //{"access_token":"38_BCHBaD83tj36xDpFDIqbPfOr4XTFTB5o6TeaFUAVYC5pn0UfiImLL1J
        // nU7jIJw2mWdU3DCzlquIt5Tqcj9HxlGMxg-SLFq7TBT5ceRn7dfQ",
        // "expires_in":7200,"refresh_token":
        // "38_3eXl1KVtn8miZRlVivUmT5PcKJ6ow5NkSgbab9dRt0mkF_x092XlP9S3RQH4dT0-HTKhwSd-J94p
        // _QXvtvR81Ui_tzA8OS_JholfaX1DzZ8","openid":"oa9wA0_clwVQ6uUbZgkQ3MgzLnAg",
        // "scope":"snsapi_login","unionid":"ovnCWwwJ3S9h_pJ4Rcz_HecQ93BI"}

        //以一个json字符串的形式返回
        String tokenResp = HttpClientUtils.httpGet(token_url);
        //装换为json对象
        JSONObject jsonObject = JSONObject.parseObject(tokenResp);
        //获取其中的关键信息
        String access_token = jsonObject.getString("access_token");
        String openid = jsonObject.getString("openid");
        //根据openid查询t_wxuser表，判断该用户是否使用微信登陆过本平台
        WxUser wxUser = wxUserMapper.loadWxUserByOpenid(openid);
        if(wxUser==null){ //为空则该用户没有使用微信登录过本平台
            /*
             那么需要将用户信息保存到t_wxuser表中，然后再跳转到绑定页面
                1. 先获取到用户的微信信息，再保存到表中
             */
            String userInfoUrl = WeChatContant.USER_INFO.replace("ACCESS_TOKEN", access_token)
                    .replace("OPENID", openid);
            String userResp = HttpClientUtils.httpGet(userInfoUrl);
            /*得到的微信信息
            * {"openid":"oa9wA03fK3J7TYwTEps8AEXR8i3U",
            * "nickname":"好久不见","sex":1,"language":"zh_CN",
            * "city":"Wuhan","province":"Hubei","country":"CN",
            * "headimgurl":"https:\/\/thirdwx.qlogo.cn\/mmopen\/vi_32\/bZredOZ2AScRe1NVUUQ90duvlzIPR2MKcWJWfDTsGJCrXiaCMsUDQibuNOAczzcVOhpt8yiaRoE77icPAlOEXane0w\/132",
            * "privilege":[],"unionid":"ovnCWwxvLYrK8WMm8AeGICq-xSxw"}
            * */
            //将得到的信息json字符串转换为对象
            JSONObject WxUserObject = JSONObject.parseObject(userResp);
            //用对象装起来
            WxUser new_wxUser = new WxUser();
            new_wxUser.setOpenid(WxUserObject.getString("openid"));
            new_wxUser.setNickname(WxUserObject.getString("nickname"));
            new_wxUser.setSex(WxUserObject.getInteger("sex"));
            new_wxUser.setHeadimgurl(WxUserObject.getString("headimgurl"));
            new_wxUser.setUnionid(WxUserObject.getString("unionid"));
            new_wxUser.setAddress(WxUserObject.getString("country")+WxUserObject.getString("province")+WxUserObject.getString("city"));
            //保存在数据库,并返回主键到对象中，
            wxUserMapper.save(new_wxUser);
            //前端根据AjaxResult中的success判断是否跳转到绑定页面，将openid携带过去
            return new AjaxResult(openid);
        }
        if(wxUser.getUser()==null){ //登陆过平台但没绑定本平台账号
            //跳转到绑定用户界面
            return new AjaxResult(openid);
        }
        //登陆过本平台，也绑定过账号
        Map<String,Object> resultMap = new HashMap<>();
        //生成一个令牌 --最好用uuid
        String token = UUID.randomUUID().toString();
        //把当前的登录用户转换为字符串  --推荐转换为 josn
        //把当前用户放到redis里面
        RedisUtils.INSTANCE.set(token,  JSONObject.toJSONString(wxUser.getUser()), 30*60);
        //1.把当前的令牌告诉前端项目
        resultMap.put("token", token);
        //2.把当前用户返回给前端
        resultMap.put("loginUser", wxUser.getUser());

        return AjaxResult.me().setResultObj(resultMap);
    }

    @Override
    public Map<String, Object> binder(Map<String, String> map) {
        Map<String,Object> resultMap = new HashMap<>();
        //1.根据用户名查询用户
        User binderUser = userMapper.checkPhone(map.get("username"));
        if(binderUser==null){ //为空则没有该用户，就直接生成该用户，并与该微信绑定
            User user = new User();
            user.setUsername(map.get("username"));
            String salt = StrUtils.getComplexRandomString(32);
            user.setPassword(MD5Utils.encrypByMd5(map.get("password")+ salt));
            user.setSalt(salt);
            userMapper.save(user);

            //保存之后将其与微信账号关联
            wxUserMapper.updateUserIdByOpenid(user.getId(),map.get("openid"));
            //然后进行登录的流程

            //token使用UUID生成
            String token = UUID.randomUUID().toString();

            //由于redis中只能存字符串，所以将对象转换为json格式的字符串(因为以后可能需要取出来再装换为对象)
            //将token存入redis中并设置过期时间
            RedisUtils.INSTANCE.set(token, JSONObject.toJSONString(user), 60*30);

            //将用户名和密码也发送过去，让其保存
            //由于需要返回多个数据，而AjaxResult只能携带一个数据过去，所以我们使用map装起来
            resultMap.put("token", token);
            resultMap.put("loginUser", user);
            return resultMap;
        }
        //如果能够查询到用户 登录的流程
        //验证密码是否正确
        String byMd5 = MD5Utils.encrypByMd5(map.get("password") + binderUser.getSalt());
        if (!byMd5.equals(binderUser.getPassword())){
            throw  new RuntimeException("密码错误");
        }
        //根据openid 修改绑定的用户
        wxUserMapper.updateUserIdByOpenid(binderUser.getId(),map.get("openid"));
        //生成一个令牌 --最好用uuid
        String token = UUID.randomUUID().toString();
        //把当前的登录用户转换为字符串  --推荐转换为 josn
        //把当前用户放到redis里面
        RedisUtils.INSTANCE.set(token,  JSONObject.toJSONString(binderUser), 30*60);
        //1.把当前的令牌告诉前端项目
        resultMap.put("token", token);
        //2.把当前用户返回给前端
        resultMap.put("loginUser", binderUser);
        return resultMap;
    }
}
